package utils

import (
	"encoding/binary"
	"math"
)

type msgPackWriter struct{}
type msgPackReader struct{}

var MsgPackWriter msgPackWriter
var MsgPackReader msgPackReader

func (msgPackWriter) PutInteger(buf []byte, val int64) (ilength int) {
	if val > 0 {
		if val <= 127 {
			buf[0] = byte(val)
			return 1
		} else if val <= 255 {
			buf[0] = 0xCC
			buf[1] = byte(val)
			return 2
		} else if val <= 65535 {
			buf[0] = 0xCD
			binary.BigEndian.PutUint16(buf[1:], uint16(val))
			return 3
		} else if val <= 0xFFFFFFFF {
			buf[0] = 0xCE
			binary.BigEndian.PutUint32(buf[1:], uint32(val))
			return 5
		} else {
			buf[0] = 0xCF
			binary.BigEndian.PutUint64(buf[1:], uint64(val))
			return 9
		}
	} else {
		if val <= math.MinInt32 {
			buf[0] = 0xD3
			binary.BigEndian.PutUint64(buf[1:], uint64(val))
			return 9
		} else if val <= math.MinInt16 {
			buf[0] = 0xD2
			binary.BigEndian.PutUint32(buf[1:], uint32(val))
			return 5
		} else if val <= math.MinInt8 {
			buf[0] = 0xD1
			binary.BigEndian.PutUint16(buf[1:], uint16(val))
			return 3
		} else if val <= -32 {
			buf[0] = 0xD0
			buf[1] = byte(val)
			return 2
		} else {
			buf[0] = byte(val)
			return 1
		}
	}
}

// / 未完成
func (msgPackReader) GetInteger(buf []byte) (rval int64, vallength int) {
	b := buf[0]
	if b >= 0 && b <= 0x7F {
		return int64(b), 1
	} else if b >= 0xE0 && b <= 0xFF {
		return int64(int8(b)), 1
	} else {
		switch b {
		case 0xC0:
			return 0, 1
		case 0xCC: // UInt8
			return int64(uint8(buf[1])), 2
		case 0xCD: // Uint16
			return int64(binary.BigEndian.Uint16(buf[1:])), 3
		case 0xCE: // uint32
			return int64(binary.BigEndian.Uint32(buf[1:])), 5
		case 0xCF: // uint64
			return int64(binary.BigEndian.Uint64(buf[1:])), 9

		}
	}
	return 0, 0

}
